

// {
//   tag:'div',
//   attrs: [{id:"app"}],
//   children:[{tag:null,text: 'hello'},{tag:"div"}]
// }

// 编译成AST语法树

const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-z]*`;  //标签名称
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;//<span:xx>
// const startTagOpen = new RegExp(`^<${`((?:${`[a-zA-Z_][\\-\\.0-9_a-zA-z]*`}\\:)?${`[a-zA-Z_][\\-\\.0-9_a-zA-z]*`})`}`) //标签开头的正则 捕获的内容是标签名
const startTagOpen = new RegExp(`^<${qnameCapture}`) //标签开头的正则 捕获的内容是标签名
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)// 匹配标签结尾的</div>
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|([^\s"'=<>`]+)))?/
const startTagClose = /^\s*(\/?)>/;   // 匹配标签闭合的> 捕获的内容是闭合标记前面的斜杠
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g


function createASTElement (tag,attrs){
  return {
    tag,
    attrs,
    children:[],
    type: 1,
    parent:null
  }
}

let root
let createParent
let stack = [] 

function start(tag, attrs) {
  let element = createASTElement(tag, attrs)

  if (!root) {
    root = element
  }

  createParent = element

  stack.push(element)

}
function charts(text) {

  text = text.replace(/s/g, '')

  if (text) {
    createParent.children.push({
      type: 3,
      text
    })
  }

}
function end(tag) {
  let element = stack.pop()
  createParent = stack[stack.length - 1]
  if (createParent) {
    element.parent = createParent.tag
    createParent.children.push(element)
  }
}


export function parseHTML(html) {
  while (html) {
    let textENd = html.indexOf('<')
    if (textENd == 0) {

      const endMatchTag = html.match(endTag)
      if (endMatchTag) {
        advance(endMatchTag[0].length)
        end(endMatchTag[1])
      } else {
        const startTagMatch = parseStartTag()
        start(startTagMatch.tagName, startTagMatch.attrs)
      }
    }

    let text
    if (textENd > 0) {
      text = html.substring(0, textENd)
      // const text =  html.slice(0,textENd)
      charts(text)
    }

    if (text) {
      advance(text.length)
    }

  }

  function parseStartTag() {
    const start = html.match(startTagOpen)
    let match = {
      tagName: start[1],
      attrs: []
    }

    advance(start[0].length)
    let attr, end


    while (!(end = html.match(startTagClose)) && (attr = html.match(attribute))) {
      match.attrs.push({ name: attr[1], value: attr[3] || attr[4] || attr[5] })
      advance(attr[0].length)
    }

    if (end) {
      advance(end[0].length)
      return match
    }
  }


  function advance(n) {
    html = html.substring(n)
  }


  return root
}